package com.telchina.workorder.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.telchina.common.core.domain.AjaxResult;
import com.telchina.common.enums.ApproveResultEnum;
import com.telchina.common.enums.ApproveStatusEnum;
import com.telchina.common.service.IBaseFlowService;
import com.telchina.common.service.IWoTaskConfigService;
import com.telchina.common.utils.DateUtils;
import com.telchina.common.utils.PageUtils;
import com.telchina.common.utils.SecurityUtils;
import com.telchina.common.utils.StringUtils;
import com.telchina.workorder.domain.WoDisregardKpi;
import com.telchina.workorder.domain.WoWorkOrder;
import com.telchina.workorder.domain.vo.WoDisregardKpiReqVO;
import com.telchina.workorder.domain.vo.WoDisregardKpiVO;
import com.telchina.workorder.mapper.WoDisregardKpiMapper;
import com.telchina.workorder.service.IWoDisregardKpiService;
import com.telchina.workorder.service.IWoWorkOrderService;
import com.telchina.workorder.third.config.BpmConfig;
import com.telchina.workorder.third.service.BpmProcessInstanceThirdService;
import com.telchina.workorder.third.service.BpmTaskThirdService;
import com.telchina.workorder.third.service.SystemThirdService;
import com.telchina.workorder.third.vo.ApproveResultDataVO;
import com.telchina.workorder.third.vo.TaskTodoItemRespVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 不及考核申请Service业务层处理
 *
 * @author konghao
 * @date 2023-02-21
 */
@Service
public class WoDisregardKpiServiceImpl implements IWoDisregardKpiService {

    public static final String BUSINESS_KEY = "disregard";
    public static final String CANDIDATE_USER = "candidateUser";

    @Autowired
    private WoDisregardKpiMapper woDisregardKpiMapper;
    @Autowired
    private BpmConfig bpmConfig;
    @Autowired
    private SystemThirdService systemThirdService;
    @Autowired
    private BpmProcessInstanceThirdService processInstanceThirdService;
    @Autowired
    private BpmTaskThirdService taskThirdService;
    @Autowired
    private IBaseFlowService baseFlowService;
    @Autowired
    private IWoWorkOrderService woWorkOrderService;
    @Autowired
    private IWoTaskConfigService woTaskConfigService;

    /**
     * 查询不及考核申请
     *
     * @param id 不及考核申请ID
     * @return 不及考核申请
     */
    @Override
    public WoDisregardKpi selectById(String id) {
        return woDisregardKpiMapper.selectById(id);
    }

    /**
     * 分页查询不及考核申请列表
     *
     * @param woDisregardKpi 不及考核申请
     * @return 不及考核申请
     */
    @Override
    public IPage<WoDisregardKpi> selectList(IPage<WoDisregardKpi> page, WoDisregardKpi woDisregardKpi) {
        return woDisregardKpiMapper.selectWoDisregardKpiPage(page, woDisregardKpi);
    }

    /**
     * 查询所有不及考核申请列表
     *
     * @param woDisregardKpi 不及考核申请
     * @return 不及考核申请
     */
    @Override
    public List<WoDisregardKpi> selectListAll(WoDisregardKpi woDisregardKpi) {
        return woDisregardKpiMapper.selectWoDisregardKpiList(woDisregardKpi, null);
    }

    /**
     * 新增不及考核申请
     *
     * @param woDisregardKpi 不及考核申请
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insert(WoDisregardKpi woDisregardKpi) throws Exception {
        // 判断是否存在审核中的不及考核申请单
        int has = woDisregardKpiMapper.selectCount(new QueryWrapper<WoDisregardKpi>().lambda()
                .eq(WoDisregardKpi::getWorkOrderNumber, woDisregardKpi.getWorkOrderNumber())
                .eq(WoDisregardKpi::getApproveStatus, ApproveStatusEnum.IN_APPROVAL.getCode()));
//        if (has > 0) {
//            return AjaxResult.error("存在审批中的不及考核申请单，不可再次提交");
//        }
        woDisregardKpi.setCreateTime(DateUtils.getNowDate());
        // 填报时间
        woDisregardKpi.setFilledTime(DateUtils.getNowDate());
        // 填报人
        woDisregardKpi.setFilledBy(SecurityUtils.getUserId());
        // 保存流程审批
        int save = woDisregardKpiMapper.insert(woDisregardKpi);
        // 启动流程审批
        String instanceId = startFlow(woDisregardKpi);
        woDisregardKpi.setInstanceId(instanceId);
        // 审核中
        woDisregardKpi.setApproveStatus(ApproveStatusEnum.IN_APPROVAL.getCode());
        woDisregardKpiMapper.updateById(woDisregardKpi);
        return save > 0 ? AjaxResult.success(woDisregardKpi) : AjaxResult.error();
    }

    /**
     * 启动工单流程
     *
     * @param woDisregardKpi
     * @return
     */
    private String startFlow(WoDisregardKpi woDisregardKpi) throws Exception {
        Map<String, Object> params = new HashMap<>();
        // 当前登录人
        params.put("userId", SecurityUtils.getUserId());
        // 流程实例key
        params.put("processDefinitionKey", bpmConfig.getDisregardProcessDefinitionKey());
        // 业务实例key
        params.put("businessKey", BUSINESS_KEY);
        // 绑定业务数据 start
        Map<String, Object> variablesParams = new HashMap<>();
        // 工单发起人所在单位
        String userIds = woTaskConfigService.getCandidateUser(bpmConfig.getDisregardProcessDefinitionKey(),
                "activity", woDisregardKpi.getWorkOrderNumber());
        variablesParams.put(CANDIDATE_USER, userIds);
        params.put("variables", variablesParams);
        // 绑定业务数据 end
        AjaxResult ajaxResult = processInstanceThirdService.createProcessInstance(params);
        if (!Objects.equals(ajaxResult.get(AjaxResult.CODE_TAG), 0)) {
            throw new RuntimeException("启动失败，提交流程异常" + ajaxResult.get(AjaxResult.MSG_TAG));
        }
        return String.valueOf(ajaxResult.get(AjaxResult.DATA_TAG));
    }

    /**
     * 修改不及考核申请
     *
     * @param woDisregardKpi 不及考核申请
     * @return 结果
     */
    @Override
    public int update(WoDisregardKpi woDisregardKpi) {
        woDisregardKpi.setUpdateTime(DateUtils.getNowDate());
        return woDisregardKpiMapper.updateById(woDisregardKpi);
    }

    /**
     * 批量删除不及考核申请
     *
     * @param ids 需要删除的不及考核申请ID
     * @return 结果
     */
    @Override
    public int deleteByIds(String[] ids) {
        return woDisregardKpiMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除不及考核申请信息
     *
     * @param id 不及考核申请ID
     * @return 结果
     */
    @Override
    public int deleteById(String id) {
        return woDisregardKpiMapper.deleteById(id);
    }

    /**
     * 不及考核申请单待办列表
     *
     * @param supervise
     * @return
     */
    @Override
    public List<WoDisregardKpiVO> selectTodoList(WoDisregardKpiReqVO supervise) {
        //  获取工单待办
        Map<String, Object> params = new HashMap<>();
        // 当前登录人
        params.put("userId", SecurityUtils.getUserId());
        // 业务实例key
        params.put("businessKey", BUSINESS_KEY);
        // 处理的范围
        params.put("assignment", "all");

        if (StringUtils.isNotEmpty(supervise.getWorkOrderNumber())) {
            supervise.setWorkOrderNumber("%" + supervise.getWorkOrderNumber() + "%");
        }

        AjaxResult ajaxResult = taskThirdService.getTodoTask(params);
        // 绑定业务数据 end
        if (!Objects.equals(ajaxResult.get(AjaxResult.CODE_TAG), 0)) {
            throw new RuntimeException("系统异常,未查询到代办信息" + ajaxResult.get(AjaxResult.MSG_TAG));
        }
        // 数据转换
        List<TaskTodoItemRespVO> taskTodoItemRespVOList = JSON.parseArray(ajaxResult.get(AjaxResult.DATA_TAG).toString(), TaskTodoItemRespVO.class);
        // 获取流程实例的id
        List<String> instanceIds = taskTodoItemRespVOList.stream()
                .map(TaskTodoItemRespVO::getProcessInstance).map(TaskTodoItemRespVO.ProcessInstance::getId).collect(Collectors.toList());
        if (instanceIds.size() == 0) {
            // 为空时返回空集合
            return new ArrayList<WoDisregardKpiVO>();
        }
        PageUtils.startPage();
        List<WoDisregardKpiVO> woDisregardKpis = woDisregardKpiMapper.selectWoDisregardKpiAndWOList(supervise, instanceIds);
        woDisregardKpis.stream().forEach(A -> {
            // 获取工作流任务数据
            A.setTaskTodoItemRespVO(taskTodoItemRespVOList.stream()
                    .filter(B -> B.getProcessInstance().getId().equals(A.getInstanceId())).collect(Collectors.toList()).get(0));
        });
        return woDisregardKpis;
    }

    /**
     * 业务单据审核处理
     *
     * @param maps
     * @return
     */
    @Override
    public AjaxResult approveSupervise(Map<String, Object> maps) throws Exception {
        // 进行数据校验
        if (Objects.isNull(maps.get("taskId"))) {
            return AjaxResult.error("任务id为空！");
        }
        // 进行数据校验
        if (Objects.isNull(maps.get("result"))) {
            return AjaxResult.error("审核意见不能为空！");
        }
        // 进行数据校验
        if (Objects.isNull(maps.get("workOrderNumber"))) {
            return AjaxResult.error("工单单号不能为空！");
        }
        // 验证任务
        baseFlowService.checkUserIdDoTask(maps.get("taskId").toString());
        // 主单单号
        String id = String.valueOf(maps.get("disregardId"));
        // 只有审核中的单据才可以审核
        WoDisregardKpi woDisregardKpi = woDisregardKpiMapper.selectOne(new QueryWrapper<WoDisregardKpi>().lambda()
                .eq(WoDisregardKpi::getId, id).eq(WoDisregardKpi::getApproveStatus,
                        ApproveStatusEnum.IN_APPROVAL.getCode()));
        if (Objects.isNull(woDisregardKpi)) {
            return AjaxResult.error("未找要审批的单据：【" + id + "】");
        }
        // 组装参数
        Map<String, Object> approveTaskParam = new HashMap<>();
        approveTaskParam.put("userId", SecurityUtils.getUserId());
        approveTaskParam.put("deptId", systemThirdService.getLoginUseDeptId());
        approveTaskParam.put("operate", ApproveResultEnum.getValueOf(maps.get("result").toString()).getDesc());
        approveTaskParam.put("id", maps.get("taskId"));
        approveTaskParam.putAll(maps);
        approveTaskParam.put("processInstId", woDisregardKpi.getInstanceId());
        // 获取下一步节点任务属性
        AjaxResult nextUserTask = taskThirdService.getNextUserTask(approveTaskParam);
        if (!Objects.equals(nextUserTask.get(AjaxResult.CODE_TAG), 0)) {
            throw new RuntimeException("系统异常,未获取到下一步审批节点：" + nextUserTask.get(AjaxResult.MSG_TAG));
        }
        JSONObject jb = JSONObject.parseObject(nextUserTask.get(AjaxResult.DATA_TAG).toString());
        if (jb.getJSONArray("outgoingFlows").size() != 0) {
            // 获取审核角色下相关人员信息
            String userIds = woTaskConfigService.getCandidateUser(bpmConfig.getDisregardProcessDefinitionKey(),
                    jb.get("id").toString(), maps.get("workOrderNumber").toString());
            // 修改流程处理人参数
            maps.put("variables", new HashMap<String, Object>() {{
                put(CANDIDATE_USER, userIds);
            }}); // 下一步处理人
            maps.put("id", maps.get("taskId"));
            AjaxResult updateTaskResult = taskThirdService.updateTaskVariable(maps);
            if (!Objects.equals(updateTaskResult.get(AjaxResult.CODE_TAG), 0)) {
                throw new RuntimeException("系统异常,参数设置失败：" + updateTaskResult.get(AjaxResult.MSG_TAG));
            }
        }
        // 任务办理  开始
        AjaxResult taskResult = new AjaxResult();
        if (maps.get("result").toString().equals(ApproveResultEnum.APPROVE.getResult())) {
            taskResult = taskThirdService.approveTask(approveTaskParam);
        } else {
            taskResult = taskThirdService.rejectTask(approveTaskParam);
        }
        if (!Objects.equals(taskResult.get(AjaxResult.CODE_TAG), 0)) {
            throw new RuntimeException("系统异常，任务转交失败" + taskResult.get(AjaxResult.MSG_TAG));
        }
        // 获取任务处理后的data数据  用来处理任务审批结果
        ApproveResultDataVO approveResultDataVO = JSONObject.parseObject(taskResult.get(AjaxResult.DATA_TAG).toString(),
                ApproveResultDataVO.class);
        if (approveResultDataVO.getStatus().equals(ApproveStatusEnum.COMPLETED.getCode())) { // 单据审核完成
            woDisregardKpi.setApproveTime(new Date());
            woDisregardKpi.setResult(approveResultDataVO.getResult());
            // 同步回写订单信息
            woWorkOrderService.updateByWorkOrderNumber(new WoWorkOrder() {{
                setWorkOrderNumber(woDisregardKpi.getWorkOrderNumber());
                setDisergardKpi("3".equals(approveResultDataVO.getResult()) ? "0" : "1");
            }});
        }
        // 审核完成 -> 批复意见
        woDisregardKpi.setReplyOpinion((StringUtils.isEmpty(woDisregardKpi.getReplyOpinion()) ? ""
                : woDisregardKpi.getReplyOpinion() + " <br/>") + SecurityUtils.getLoginUser().getUsername() + "：" + maps.get("reason").toString());
        // 审核状态
        woDisregardKpi.setApproveStatus(approveResultDataVO.getStatus());
        woDisregardKpiMapper.updateById(woDisregardKpi);
        return AjaxResult.success("操作成功");
    }
}
